<?php

namespace App\Exceptions;

use App\Consts\ExceptionCodeConst;
use App\Consts\GlobalConst;
use Illuminate\Support\Facades\Log;
use \Symfony\Component\HttpKernel\Exception\HttpException;
use Exception;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that should not be reported.
     *
     * @var array
     */
    protected $dontReport = [
        \Illuminate\Auth\AuthenticationException::class,
        \Illuminate\Auth\Access\AuthorizationException::class,
        \Symfony\Component\HttpKernel\Exception\HttpException::class,
        \Illuminate\Database\Eloquent\ModelNotFoundException::class,
        \Illuminate\Session\TokenMismatchException::class,
        \Illuminate\Validation\ValidationException::class,
    ];

    /**
     * Report or log an exception.
     *
     * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
     *
     * @param  \Exception  $exception
     * @return void
     */
    public function report(Exception $exception)
    {
        parent::report($exception);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception  $exception
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function render($request, Exception $exception)
    {
        $code = 0;
        $file = '';
        $flag = GlobalConst::ERROR_FILE_FLAG;
        $message = $exception->getMessage();
        if ($exception instanceof HttpException) {
            $code = $exception->getStatusCode();
            if (in_array($code, [
                ExceptionCodeConst::ROUTE_NOT_FOUND,
                ExceptionCodeConst::ROUTE_NOT_ALLOWED,
                ExceptionCodeConst::ROUTE_PAGE_EXPIRED,
            ])) {
                return $this->renderHttpException($exception);
            }
        }
        if (false !== strpos($message, $flag)) {
            list($message, $file) = explode($flag, $message);
        }
        $message = $message ? : lang('Server Error');
        if (false !== strpos($message, '# [') && false !== strpos($message, '] - ')) {
            $message = explode(' - ', $message);
            $message = $message[1];
        }
        $files = $exception->getFile() . ' - ' . $exception->getLine();
        if (strpos($files, 'helper.func.php') || strpos($files, 'BaseController.php')) {
            foreach ($exception->getTrace() as $key => $val) {
                if (strpos($val['file'], 'Route.php')) {
                    $files = $val;
                    break;
                }
            }
            $files = $files ?: __FILE__ . ' - ' . __LINE__;
        }
        $info = [
            'status' => 'failed',
            'code' => $code ? : ($exception->getCode() ? : ExceptionCodeConst::SERVER_FAIL),
            'msg' => $message,
            'result' => isProd() ? [] : [
                'file' => $file ? $flag . $file : $files,
                'request' =>  $request->all(),
            ]
        ];
        Log::error('[CATCH][RENDER] - ' . json_encode($info));
        return response()->json($info);
        //return parent::render($request, $exception);
    }

    /**
     * Convert an authentication exception into an unauthenticated response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Illuminate\Auth\AuthenticationException  $exception
     * @return \Illuminate\Http\Response
     */
    protected function unauthenticated($request, AuthenticationException $exception)
    {
        if ($request->expectsJson()) {
            return response()->json(['error' => 'Unauthenticated.'], 401);
        }

        return redirect()->guest(route('login'));
    }
}
